"""
Git操作模块

封装基本的Git操作，包括仓库初始化、文件提交、推送等。
"""

import os
import logging
from typing import Dict, List, Any, Optional
from pathlib import Path
import git
from git import Repo


class GitOperations:
    """Git操作类
    
    封装基本的Git操作，包括仓库初始化、文件提交、推送等。
    """
    
    def __init__(self, logger: logging.Logger = None):
        """初始化Git操作类
        
        参数:
            logger (logging.Logger): 日志记录器
        """
        self.logger = logger or logging.getLogger(__name__)
    
    def init_repository(self, local_path: str) -> Dict[str, Any]:
        """初始化本地Git仓库
        
        参数:
            local_path (str): 本地仓库路径
            
        返回:
            Dict[str, Any]: 初始化结果
        """
        try:
            if os.path.exists(local_path):
                # 如果目录已存在，尝试打开现有仓库
                if os.path.exists(os.path.join(local_path, '.git')):
                    repo = Repo(local_path)
                    result = {
                        "success": True,
                        "local_path": local_path,
                        "existing_repo": True,
                        "message": "使用现有Git仓库"
                    }
                else:
                    # 目录存在但没有.git目录，初始化新仓库
                    repo = Repo.init(local_path)
                    self._create_initial_structure(repo)
                    result = {
                        "success": True,
                        "local_path": local_path,
                        "existing_repo": False,
                        "message": "初始化新Git仓库"
                    }
            else:
                # 创建新仓库
                os.makedirs(local_path, exist_ok=True)
                repo = Repo.init(local_path)
                self._create_initial_structure(repo)
                result = {
                    "success": True,
                    "local_path": local_path,
                    "existing_repo": False,
                    "message": "创建并初始化新Git仓库"
                }
            
            self.logger.info(f"Git仓库初始化成功: {local_path}")
            return result
            
        except Exception as e:
            self.logger.error(f"初始化Git仓库失败: {e}")
            return {
                "success": False,
                "error": str(e)
            }
    
    def commit_file(self, repo_path: str, file_path: str, 
                   commit_message: str) -> Dict[str, Any]:
        """提交文件到Git仓库
        
        参数:
            repo_path (str): 仓库路径
            file_path (str): 要提交的文件路径
            commit_message (str): 提交信息
            
        返回:
            Dict[str, Any]: 提交结果
        """
        try:
            if not os.path.exists(repo_path):
                return {"success": False, "error": "仓库路径不存在"}
            
            repo = Repo(repo_path)
            
            # 确保文件在仓库工作目录内
            if not file_path.startswith(repo_path):
                return {"success": False, "error": "文件不在仓库目录内"}
            
            # 添加文件到暂存区
            relative_path = os.path.relpath(file_path, repo_path)
            repo.git.add(relative_path)
            
            # 检查是否有更改需要提交
            if repo.is_dirty() or repo.untracked_files:
                # 提交更改
                commit = repo.index.commit(commit_message)
                
                result = {
                    "success": True,
                    "commit_hash": commit.hexsha[:12],
                    "commit_message": commit_message,
                    "files_committed": [relative_path]
                }
                
                self.logger.info(f"文件提交成功: {relative_path}")
                return result
            else:
                return {
                    "success": True,
                    "message": "没有更改需要提交",
                    "files_committed": []
                }
            
        except Exception as e:
            self.logger.error(f"提交文件失败: {e}")
            return {
                "success": False,
                "error": str(e)
            }
    
    def push_to_remote(self, repo_path: str, remote_name: str = "origin",
                      branch: str = "main") -> Dict[str, Any]:
        """推送到远程仓库
        
        参数:
            repo_path (str): 仓库路径
            remote_name (str): 远程仓库名称
            branch (str): 分支名称
            
        返回:
            Dict[str, Any]: 推送结果
        """
        try:
            if not os.path.exists(repo_path):
                return {"success": False, "error": "仓库路径不存在"}
            
            repo = Repo(repo_path)
            
            # 检查是否有远程仓库配置
            if remote_name not in repo.remotes:
                self.logger.info(f"远程仓库 {remote_name} 未配置，跳过推送")
                return {
                    "success": True,
                    "message": "远程仓库未配置，跳过推送",
                    "pushed": False
                }
            
            remote = repo.remotes[remote_name]
            
            # 执行推送
            push_info = remote.push(branch)
            
            # 分析推送结果
            pushed_commits = 0
            for info in push_info:
                if info.flags & info.ERROR == 0:
                    pushed_commits += 1
            
            result = {
                "success": True,
                "remote": remote_name,
                "branch": branch,
                "pushed_commits": pushed_commits,
                "pushed": pushed_commits > 0
            }
            
            if pushed_commits > 0:
                self.logger.info(f"成功推送到 {remote_name}/{branch}")
            else:
                self.logger.info(f"没有新的提交需要推送")
            
            return result
            
        except Exception as e:
            self.logger.error(f"推送失败: {e}")
            return {
                "success": False,
                "error": str(e)
            }
    
    def get_repository_info(self, repo_path: str) -> Dict[str, Any]:
        """获取仓库信息
        
        参数:
            repo_path (str): 仓库路径
            
        返回:
            Dict[str, Any]: 仓库信息
        """
        try:
            if not os.path.exists(repo_path):
                return {"error": "仓库路径不存在"}
            
            repo = Repo(repo_path)
            
            # 获取当前分支
            try:
                branch = repo.active_branch.name
            except:
                branch = "detached"
            
            # 获取提交信息
            commits = list(repo.iter_commits())
            last_commit = commits[0] if commits else None
            
            # 获取远程仓库信息
            remotes = []
            for remote in repo.remotes:
                remotes.append({
                    'name': remote.name,
                    'url': remote.url
                })
            
            # 检查是否有未提交的更改
            is_dirty = repo.is_dirty()
            untracked_files = repo.untracked_files
            
            result = {
                "local_path": repo.working_dir,
                "branch": branch,
                "commit_count": len(commits),
                "last_commit": last_commit.hexsha[:12] if last_commit else "",
                "last_commit_message": last_commit.message.strip() if last_commit else "",
                "last_commit_time": last_commit.committed_datetime.isoformat() if last_commit else "",
                "remotes": remotes,
                "is_dirty": is_dirty,
                "untracked_files_count": len(untracked_files)
            }
            
            return result
            
        except Exception as e:
            self.logger.error(f"获取仓库信息失败: {e}")
            return {"error": str(e)}
    
    def _create_initial_structure(self, repo: Repo) -> None:
        """创建初始仓库结构
        
        参数:
            repo (Repo): Git仓库对象
        """
        try:
            # 创建README文件
            readme_content = """# 数据库备份仓库

这个仓库用于存储数据库备份文件。

## 文件结构
- `backups/`: 备份文件目录
- `reports/`: 差异报告目录

## 使用说明
备份文件会自动上传到此仓库进行版本管理。
"""
            
            readme_path = os.path.join(repo.working_dir, "README.md")
            with open(readme_path, 'w', encoding='utf-8') as f:
                f.write(readme_content)
            
            # 创建目录结构
            os.makedirs(os.path.join(repo.working_dir, "backups"), exist_ok=True)
            os.makedirs(os.path.join(repo.working_dir, "reports"), exist_ok=True)
            
            # 创建.gitignore文件
            gitignore_content = """# 临时文件
*.tmp
*.temp

# 日志文件
*.log

# 系统文件
.DS_Store
Thumbs.db

# 备份文件（保留SQL文件）
# !*.sql
"""
            gitignore_path = os.path.join(repo.working_dir, ".gitignore")
            with open(gitignore_path, 'w', encoding='utf-8') as f:
                f.write(gitignore_content)
            
            # 添加文件并提交
            repo.git.add("README.md")
            repo.git.add(".gitignore")
            repo.git.add("backups/")
            repo.git.add("reports/")
            
            repo.index.commit("Initial commit: Add repository structure")
            
            self.logger.info("创建初始仓库结构完成")
            
        except Exception as e:
            self.logger.error(f"创建初始仓库结构失败: {e}")
            raise
    
    def cleanup(self) -> None:
        """清理Git操作资源
        
        这个方法用于清理Git操作相关的资源。
        """
        # GitOperations类目前没有需要特殊清理的资源
        # 这个方法为空实现，保持接口一致性
        pass